package com.ruoyi.analysis.service.impl;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.analysis.domain.AnalyzePayloadReq;
import com.ruoyi.analysis.domain.AnalyzePayloadResp;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.model.domain.ModelDetails;
import com.ruoyi.model.domain.ModelPreprocessing;
import com.ruoyi.model.domain.ModelWaveSelect;
import com.ruoyi.model.service.IModelDetailsService;
import com.ruoyi.model.service.IModelPreprocessingService;
import com.ruoyi.model.service.IModelWaveSelectService;
import com.ruoyi.spectrum.domain.SampleSpectrumDfb;
import com.ruoyi.spectrum.service.ISampleSpectrumDfbService;
import com.ruoyi.system.domain.SNUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.analysis.mapper.OfflineHistoryMapper;
import com.ruoyi.analysis.domain.OfflineHistory;
import com.ruoyi.analysis.service.IOfflineHistoryService;

/**
 * 离线分析历史Service业务层处理
 * 
 * @author weihanqiang
 * @date 2025-06-19
 */
@Service
public class OfflineHistoryServiceImpl implements IOfflineHistoryService 
{
    @Autowired
    private SNUtil snUtil;

    @Autowired
    private OfflineHistoryMapper offlineHistoryMapper;

    @Autowired
    private IModelDetailsService modelDetailsService;

    @Autowired
    private ISampleSpectrumDfbService sampleSpectrumDfbService;

    @Autowired
    private IModelWaveSelectService modelWaveSelectService;

    @Autowired
    private IModelPreprocessingService modelPreprocessingService;

    /**
     * 查询离线分析历史
     * 
     * @param offlineResultId 离线分析历史主键
     * @return 离线分析历史
     */
    @Override
    public OfflineHistory selectOfflineHistoryByOfflineResultId(Long offlineResultId)
    {
        return offlineHistoryMapper.selectOfflineHistoryByOfflineResultId(offlineResultId);
    }

    /**
     * 查询离线分析历史列表
     * 
     * @param offlineHistory 离线分析历史
     * @return 离线分析历史
     */
    @Override
    public List<OfflineHistory> selectOfflineHistoryList(OfflineHistory offlineHistory)
    {
        return offlineHistoryMapper.selectOfflineHistoryList(offlineHistory);
    }

    /**
     * 新增离线分析历史
     * 
     * @param offlineHistory 离线分析历史
     * @return 结果
     */
    @Override
    public int insertOfflineHistory(OfflineHistory offlineHistory)
    {
        String offline_result_no = snUtil.generateSN("offline_history", "offline_result_no", "yyyyMMdd", "LH", 4);
        offlineHistory.setOfflineResultNo(offline_result_no);
        offlineHistory.setCreateTime(DateUtils.getNowDate());
        return offlineHistoryMapper.insertOfflineHistory(offlineHistory);
    }

    /**
     * 修改离线分析历史
     * 
     * @param offlineHistory 离线分析历史
     * @return 结果
     */
    @Override
    public int updateOfflineHistory(OfflineHistory offlineHistory)
    {
        return offlineHistoryMapper.updateOfflineHistory(offlineHistory);
    }

    /**
     * 批量删除离线分析历史
     * 
     * @param offlineResultIds 需要删除的离线分析历史主键
     * @return 结果
     */
    @Override
    public int deleteOfflineHistoryByOfflineResultIds(Long[] offlineResultIds)
    {
        return offlineHistoryMapper.deleteOfflineHistoryByOfflineResultIds(offlineResultIds);
    }

    /**
     * 删除离线分析历史信息
     * 
     * @param offlineResultId 离线分析历史主键
     * @return 结果
     */
    @Override
    public int deleteOfflineHistoryByOfflineResultId(Long offlineResultId)
    {
        return offlineHistoryMapper.deleteOfflineHistoryByOfflineResultId(offlineResultId);
    }
    
    /**
     * 根据分析请求参数生成分析响应数据
     * 
     * @param req 分析请求参数
     * @return 分析响应数据
     */
    @Override
    public AnalyzePayloadResp analyzePayload(AnalyzePayloadReq req) {
        AnalyzePayloadResp resp = new AnalyzePayloadResp();

        // 根据modelId获取模型详情（intercept和coef）
        ModelDetails modelDetails = getModelDetailsByModelId(req.getModelId());
        if (modelDetails != null) {
            resp.setIntercept(modelDetails.getIntercept());
            resp.setCoef(modelDetails.getCoef());
        }

        // 根据sampleSpectrumNo获取波长数据
        SampleSpectrumDfb sampleSpectrum = getSampleSpectrumByNo(req.getSampleSpectrumNo());
        if (sampleSpectrum != null) {
            resp.setWaveData(sampleSpectrum.getWavelength());
        }

        // 根据modelId获取选中的波长索引
        ModelWaveSelect modelWaveSelect = getModelWaveSelectByModelId(req.getModelId());
        if (modelWaveSelect != null) {
            resp.setSelectedIndices(modelWaveSelect.getSelectedIndices());
        }

        // 根据modelId获取预处理序列
        ModelPreprocessing modelPreprocessing = getModelPreprocessingByModelId(req.getModelId());
        // 四种预处理方法有过程参数：x_center_mean 对应 均值中心化，x_msc_mean 对应 msc，x_standar_mean,x_standar_scale 对应 standar，x_nor_max,x_nor_min 对应 normalization
        // modelPreprocessing.getPreprocessingResult()里面可能包含有x_center_mean、x_msc_mean、x_standar_mean、x_standar_scale、x_nor_max、x_nor_min这些预处理过程参数，使用json格式保存
        // modelPreprocessing.getPreprocessingSequence()里面是预处理方法，我需要把预处理过程参数对应地填入预处理方法中，构造出一个ValidPreSequence返回给前端
        if (modelPreprocessing != null) {
            try {
                ObjectMapper mapper = new ObjectMapper();

                // 1. 获取 preprocessing_sequence（方法序列）
                ArrayNode sequenceArray = (ArrayNode) mapper.readTree(modelPreprocessing.getPreprocessingSequence());

                // 2. 获取 preprocessing_result（参数）
                JsonNode resultNode = mapper.readTree(modelPreprocessing.getPreprocessingResult());

                // 3. 遍历每个方法，将对应参数注入
                for (JsonNode node : sequenceArray) {
                    ObjectNode root = (ObjectNode) node.get("root");
                    if (root == null){
                        continue;
                    }

                    String method = root.path("method").asText();

                    switch (method) {
                        case "centering":
                            ObjectNode centeringParams = mapper.createObjectNode();
                            if (resultNode.has("x_center_mean")) {
                                // 获取x_center_mean对应的JSON数组（二维数组）
                                JsonNode xCenterMeanNode = resultNode.get("x_center_mean");
                                // 判断是否为数组且有元素（处理二维数组的情况，如[[...]]）
                                if (xCenterMeanNode.isArray() && xCenterMeanNode.size() > 0) {
                                    // 取二维数组的第一个元素作为一维数组
                                    JsonNode firstElement = xCenterMeanNode.get(0);
                                    if (firstElement.isArray()) {
                                        // 将内层一维数组设置到params中
                                        centeringParams.set("x_mean", firstElement);
                                    } else {
                                        // 若本身已是一维数组，直接设置（兼容边界情况）
                                        centeringParams.set("x_mean", xCenterMeanNode);
                                    }
                                }
                            }
                            if (centeringParams.size() > 0) {
                                root.set("params", centeringParams);
                            }
                            break;
                        case "msc":
                            ObjectNode mscParams = mapper.createObjectNode();
                            if (resultNode.has("x_msc_mean")) {
                                mscParams.set("x_mean", resultNode.get("x_msc_mean"));
                            }
                            if (mscParams.size() > 0) {
                                root.set("params", mscParams);
                            }
                            break;
                        case "standardization":
                            ObjectNode standarParams = mapper.createObjectNode();
                            if (resultNode.has("x_standar_mean")) {
                                standarParams.set("x_mean", resultNode.get("x_standar_mean"));
                            }
                            if (resultNode.has("x_standar_scale")) {
                                standarParams.set("scale", resultNode.get("x_standar_scale"));
                            }
                            if (standarParams.size() > 0) {
                                root.set("params", standarParams);
                            }
                            break;
                        case "normalization":
                            ObjectNode norParams = mapper.createObjectNode();
                            if (resultNode.has("x_nor_max")) {
                                norParams.set("data_max", resultNode.get("x_nor_max"));
                            }
                            if (resultNode.has("x_nor_min")) {
                                norParams.set("data_min", resultNode.get("x_nor_min"));
                            }
                            if (norParams.size() > 0) {
                                root.set("params", norParams);
                            }
                            break;
                        default:
                            break;
                    }
                }

                // 4. 转为字符串返回
                resp.setValidPreSequence(mapper.writeValueAsString(sequenceArray));

            } catch (Exception e) {
                e.printStackTrace();
                resp.setValidPreSequence("[]");
            }
        }
        return resp;
    }

    /**
     * 根据模型编号获取模型详情
     *
     * @param modelId 模型编号
     * @return 模型详情
     */
    private ModelDetails getModelDetailsByModelId(Long modelId) {
        if (modelId == null) {
            return null;
        }
        ModelDetails modelDetails = new ModelDetails();
        modelDetails.setModelId(modelId);
        modelDetails.setIsDelete(0L);
        List<ModelDetails> list = modelDetailsService.selectModelDetailsList(modelDetails);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * 根据样品光谱编号获取样品光谱
     *
     * @param sampleSpectrumNo 样品光谱编号
     * @return 样品光谱
     */
    private SampleSpectrumDfb getSampleSpectrumByNo(String sampleSpectrumNo) {
        if (StringUtils.isEmpty(sampleSpectrumNo)) {
            return null;
        }
        SampleSpectrumDfb sampleSpectrumDfb = new SampleSpectrumDfb();
        sampleSpectrumDfb.setSampleSpectrumDfbNo(sampleSpectrumNo);
        List<SampleSpectrumDfb> list = sampleSpectrumDfbService.selectSampleSpectrumDfbList(sampleSpectrumDfb);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * 根据模型编号获取波长选择信息
     *
     * @param modelId 模型编号
     * @return 波长选择信息
     */
    private ModelWaveSelect getModelWaveSelectByModelId(Long modelId) {
        if (modelId == null) {
            return null;
        }
        ModelWaveSelect modelWaveSelect = new ModelWaveSelect();
        modelWaveSelect.setModelId(String.valueOf(modelId));
        modelWaveSelect.setIsDelete(0L);
        List<ModelWaveSelect> list = modelWaveSelectService.selectModelWaveSelectList(modelWaveSelect);
        return list.isEmpty() ? null : list.get(0);
    }

    /**
     * 根据模型编号获取预处理信息
     *
     * @param modelId 模型编号
     * @return 预处理信息
     */
    private ModelPreprocessing getModelPreprocessingByModelId(Long modelId) {
        if (StringUtils.isEmpty(String.valueOf(modelId))) {
            return null;
        }
        ModelPreprocessing modelPreprocessing = new ModelPreprocessing();
        modelPreprocessing.setModelId(String.valueOf(modelId));
        List<ModelPreprocessing> list = modelPreprocessingService.selectModelPreprocessingList(modelPreprocessing);
        return list.isEmpty() ? null : list.get(0);
    }
}